/*******************************************************************************
  * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
  * @file     varCounter.c
  * @author   UartTFT Application Team
  * @version  V0.0.1
  * @date     2023-01-04
  * @brief    This file contains the functions prototypes for the UartTFT
  *           Application display firmware.
 ********************************************************************************/
#include "varCounter.h"
#include "levetop.h"
#include "data.h"
#include "rtc.h"

Var_Count_Info gVar_Count_Info[VAR_COUNT_SIZE];
uint8_t Var_Count_num = 0;
uint8_t Var_Count_flag = 0;

void Check_Var_Count(void)
{
	if (Var_Count_num > 0 && Var_Count_flag == 1)
	{
		Var_Count_flag = 0;
		for (uint8_t i = 0; i < Var_Count_num; i++)
			gVar_Count_Info[i].t_c++;
		for (uint8_t i = 0; i < Var_Count_num; i++)
		{
			if (gVar_Count_Info[i].t_c >= gVar_Count_Info[i].t_d)
			{
				if ((var[gVar_Count_Info[i].c_add * 2] << 8) + var[gVar_Count_Info[i].c_add * 2 + 1] == gVar_Count_Info[i].V_loop
					|| (var[gVar_Count_Info[i].c_add * 2] << 8) + var[gVar_Count_Info[i].c_add * 2 + 1] == gVar_Count_Info[i].V_once)
				Run_Var_Count(i); // When a window timing time expires, switch pictures
				gVar_Count_Info[i].t_c = 0;
			}
		}
	}
}

/*Variable_Count display*/
void Variable_Count(uint8_t type, uint8_t *buff)
{
	uint16_t pointer = 0;

	if (type == 0)
	{
		gVar_Count_Info[Var_Count_num].v_add = (buff[5] + (buff[6] << 8));
		gVar_Count_Info[Var_Count_num].v_type = buff[7];
		gVar_Count_Info[Var_Count_num].c_add = buff[8] + (buff[9] << 8);
		gVar_Count_Info[Var_Count_num].V_loop = buff[10] + (buff[11] << 8);
		gVar_Count_Info[Var_Count_num].V_once = buff[12] + (buff[13] << 8);
		gVar_Count_Info[Var_Count_num].V_stop = buff[14] + (buff[15] << 8);
		gVar_Count_Info[Var_Count_num].Vmin = ((long long)((buff[16] << 24) + (buff[17] << 16) + (buff[18] << 8) + buff[19]) << 32)
												| (long long)((buff[20] << 24) + (buff[21] << 16) + (buff[22] << 8) + buff[23]);
		gVar_Count_Info[Var_Count_num].Vmax = ((long long)((buff[24] << 24) + (buff[25] << 16) + (buff[26] << 8) + buff[27]) << 32)
											| (long long)((buff[28] << 24) + (buff[29] << 16) + (buff[30] << 8) + buff[31]);
		gVar_Count_Info[Var_Count_num].step = buff[32] + (buff[33] << 8);
		gVar_Count_Info[Var_Count_num].t_d = buff[34] + (buff[35] << 8);
		gVar_Count_Info[Var_Count_num].t_c = 0;
		gVar_Count_Info[Var_Count_num].var_addr[0] = buff[36] + (buff[37] << 8);
		gVar_Count_Info[Var_Count_num].var[0] = buff[38] + (buff[39] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[1] = buff[40] + (buff[41] << 8);
		gVar_Count_Info[Var_Count_num].var[1] = buff[42] + (buff[43] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[2] = buff[44] + (buff[45] << 8);
		gVar_Count_Info[Var_Count_num].var[2] = buff[46] + (buff[47] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[3] = buff[48] + (buff[49] << 8);
		gVar_Count_Info[Var_Count_num].var[3] = buff[50] + (buff[51] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[4] = buff[52] + (buff[53] << 8);
		gVar_Count_Info[Var_Count_num].var[4] = buff[54] + (buff[55] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[5] = buff[56] + (buff[57] << 8);
		gVar_Count_Info[Var_Count_num].var[5] = buff[58] + (buff[59] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[6] = buff[60] + (buff[61] << 8);
		gVar_Count_Info[Var_Count_num].var[6] = buff[62] + (buff[63] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[7] = buff[64] + (buff[65] << 8);
		gVar_Count_Info[Var_Count_num].var[7] = buff[66] + (buff[67] << 8);
		gVar_Count_Info[Var_Count_num].mode = buff[68];
		gVar_Count_Info[Var_Count_num].feedback = buff[69];
	}
	else if (type == 1)
	{
		pointer = (buff[2] + (buff[3] << 8)) * 2;
		gVar_Count_Info[Var_Count_num].v_add = var[pointer + 1] + (var[pointer + 2] << 8);
		gVar_Count_Info[Var_Count_num].v_type = var[pointer + 3];
		gVar_Count_Info[Var_Count_num].c_add = var[pointer + 4] + (var[pointer + 5] << 8);
		gVar_Count_Info[Var_Count_num].V_loop = var[pointer + 6] + (var[pointer + 7] << 8);
		gVar_Count_Info[Var_Count_num].V_once = var[pointer + 8] + (var[pointer + 9] << 8);
		gVar_Count_Info[Var_Count_num].V_stop = var[pointer + 10] + (var[pointer + 11] << 8);
		gVar_Count_Info[Var_Count_num].Vmin = ((long long)((var[pointer + 12] << 24) + (var[pointer + 13] << 16) + (var[pointer + 14] << 8) + var[pointer + 15]) << 32)
											| (long long)((var[pointer + 16] << 24) + (var[pointer + 17] << 16) + (var[pointer + 18] << 8) + var[pointer + 19]);
		gVar_Count_Info[Var_Count_num].Vmax = ((long long)((var[pointer + 20] << 24) + (var[pointer + 21] << 16) + (var[pointer + 22] << 8) + var[pointer + 23]) << 32)
											| (long long)((var[pointer + 24] << 24) + (var[pointer + 25] << 16) + (var[pointer + 26] << 8) + var[pointer + 27]);
		gVar_Count_Info[Var_Count_num].step = var[pointer + 28] + (var[pointer + 29] << 8);
		gVar_Count_Info[Var_Count_num].t_d = var[pointer + 30] + (var[pointer + 31] << 8);
		gVar_Count_Info[Var_Count_num].t_c = 0;
		gVar_Count_Info[Var_Count_num].var_addr[0] = var[pointer + 32] + (var[pointer + 33] << 8);
		gVar_Count_Info[Var_Count_num].var[0] = var[pointer + 34] + (var[pointer + 35] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[1] = var[pointer + 36] + (var[pointer + 37] << 8);
		gVar_Count_Info[Var_Count_num].var[1] = var[pointer + 38] + (var[pointer + 39] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[2] = var[pointer + 40] + (var[pointer + 41] << 8);
		gVar_Count_Info[Var_Count_num].var[2] = var[pointer + 42] + (var[pointer + 43] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[3] = var[pointer + 44] + (var[pointer + 45] << 8);
		gVar_Count_Info[Var_Count_num].var[3] = var[pointer + 46] + (var[pointer + 47] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[4] = var[pointer + 48] + (var[pointer + 49] << 8);
		gVar_Count_Info[Var_Count_num].var[4] = var[pointer + 50] + (var[pointer + 51] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[5] = var[pointer + 52] + (var[pointer + 53] << 8);
		gVar_Count_Info[Var_Count_num].var[5] = var[pointer + 54] + (var[pointer + 55] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[6] = var[pointer + 56] + (var[pointer + 57] << 8);
		gVar_Count_Info[Var_Count_num].var[6] = var[pointer + 58] + (var[pointer + 59] << 8);
		gVar_Count_Info[Var_Count_num].var_addr[7] = var[pointer + 60] + (var[pointer + 61] << 8);
		gVar_Count_Info[Var_Count_num].var[7] = var[pointer + 62] + (var[pointer + 63] << 8);
		gVar_Count_Info[Var_Count_num].mode = var[pointer + 64];
		gVar_Count_Info[Var_Count_num].feedback = var[pointer + 65];
	}

	// Var_AddrRemapping(&gVar_Count_Info[Var_Count_num].v_add);
	for(uint8_t i=0;i<8;i++)
		Var_AddrRemapping(&gVar_Count_Info[Var_Count_num].var_addr[i]);

	Var_Count_num ++;
}

void Run_Var_Count(uint8_t num)
{
	uint8_t finish = 0;
	uint8_t rebuf[20];
	uint8_t page_flag = 0;

	int8_t sum1 = 0;
	int16_t sum2 = 0;
	int32_t sum4 = 0;
	long long temp = 0;

	if (gVar_Count_Info[num].v_type == 0 )
	{
		temp = var[gVar_Count_Info[num].v_add * 2 + 1];
	}
	else if(gVar_Count_Info[num].v_type == 0x80 )
	{
		sum1 = var[gVar_Count_Info[num].v_add * 2 + 1];
		temp = sum1;
	}
	else if (gVar_Count_Info[num].v_type == 1)
	{
		temp = (var[gVar_Count_Info[num].v_add * 2] << 8) + var[gVar_Count_Info[num].v_add * 2 + 1];
	}
	else if (gVar_Count_Info[num].v_type == 0x81)
	{
		sum2 = (var[gVar_Count_Info[num].v_add * 2] << 8) + var[gVar_Count_Info[num].v_add * 2 + 1];
		temp = sum2;
	}
	else if (gVar_Count_Info[num].v_type == 2)
	{
		temp = (var[gVar_Count_Info[num].v_add * 2] << 24) + (var[gVar_Count_Info[num].v_add * 2 + 1] << 16) + (var[gVar_Count_Info[num].v_add * 2 + 2] << 8) + var[gVar_Count_Info[num].v_add * 2 + 3];
	}
	else if (gVar_Count_Info[num].v_type == 0x82)
	{
		sum4 = (var[gVar_Count_Info[num].v_add * 2] << 24) + (var[gVar_Count_Info[num].v_add * 2 + 1] << 16) + (var[gVar_Count_Info[num].v_add * 2 + 2] << 8) + var[gVar_Count_Info[num].v_add * 2 + 3];
		temp = sum4;
	}
	else if (gVar_Count_Info[num].v_type == 3 || gVar_Count_Info[num].v_type == 0x83)
	{
		temp = ((long long)((var[gVar_Count_Info[num].v_add * 2] << 24) + (var[gVar_Count_Info[num].v_add * 2 + 1] << 16) + (var[gVar_Count_Info[num].v_add * 2 + 2] << 8) + var[gVar_Count_Info[num].v_add * 2 + 3]) << 32);
		temp = temp | (long long)((var[gVar_Count_Info[num].v_add * 2 + 4] << 24) + (var[gVar_Count_Info[num].v_add * 2 + 5] << 16) + (var[gVar_Count_Info[num].v_add * 2 + 6] << 8) + var[gVar_Count_Info[num].v_add * 2 + 7]);
	}

	if ((var[gVar_Count_Info[num].c_add * 2] << 8) + var[gVar_Count_Info[num].c_add * 2 + 1] == gVar_Count_Info[num].V_loop)
	{
		if (gVar_Count_Info[num].mode == 1)	//+
		{
			if (temp + gVar_Count_Info[num].step < gVar_Count_Info[num].Vmin || temp >= gVar_Count_Info[num].Vmax)
			{
				temp = gVar_Count_Info[num].Vmin;
			}
			else if (temp <  gVar_Count_Info[num].Vmax && temp + gVar_Count_Info[num].step > gVar_Count_Info[num].Vmax)
				temp = gVar_Count_Info[num].Vmax;
			else
				temp += gVar_Count_Info[num].step;

		}
		else if (gVar_Count_Info[num].mode == 0)
		{
			if (temp - gVar_Count_Info[num].step < gVar_Count_Info[num].Vmin && temp > gVar_Count_Info[num].Vmin)
				temp = gVar_Count_Info[num].Vmin;
			else if (temp - gVar_Count_Info[num].step >  gVar_Count_Info[num].Vmax || temp <= gVar_Count_Info[num].Vmin)
				temp = gVar_Count_Info[num].Vmax;
			else
				temp -= gVar_Count_Info[num].step;
		}
	}
	else if ((var[gVar_Count_Info[num].c_add * 2] << 8) + var[gVar_Count_Info[num].c_add * 2 + 1] == gVar_Count_Info[num].V_once)
	{
		if (gVar_Count_Info[num].mode == 1)	//+
		{
			if (temp + gVar_Count_Info[num].step < gVar_Count_Info[num].Vmin)
				temp = gVar_Count_Info[num].Vmin;
			else if (temp + gVar_Count_Info[num].step > gVar_Count_Info[num].Vmax)
				temp = gVar_Count_Info[num].Vmax;
			else
				temp += gVar_Count_Info[num].step;
			if (temp == gVar_Count_Info[num].Vmax)
				finish = 1;
		}
		else if (gVar_Count_Info[num].mode == 0)	//-
		{
			if (temp - gVar_Count_Info[num].step < gVar_Count_Info[num].Vmin)
				temp = gVar_Count_Info[num].Vmin;
			else if (temp - gVar_Count_Info[num].step > gVar_Count_Info[num].Vmax)
				temp = gVar_Count_Info[num].Vmax;
			else
				temp -= gVar_Count_Info[num].step;

			if (temp == gVar_Count_Info[num].Vmin)
				finish = 1;
		}
	}

	if (gVar_Count_Info[num].v_type == 0 || gVar_Count_Info[num].v_type == 0x80)
	{
		var[gVar_Count_Info[num].v_add * 2 + 1] = temp & 0xFF;
	}
	else if (gVar_Count_Info[num].v_type == 1 || gVar_Count_Info[num].v_type == 0x81)
	{
		var[gVar_Count_Info[num].v_add * 2] = (temp >> 8) & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 1] = temp & 0xFF;
	}
	else if (gVar_Count_Info[num].v_type == 2 || gVar_Count_Info[num].v_type == 0x82)
	{
		var[gVar_Count_Info[num].v_add * 2] = (temp >> 24) & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 1] = (temp >> 16) & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 2] = (temp >> 8) & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 3] = temp & 0xFF;
	}
	else if (gVar_Count_Info[num].v_type == 3 || gVar_Count_Info[num].v_type == 0x83)
	{
		var[gVar_Count_Info[num].v_add * 2] = temp >> 56 & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 1] = temp >> 48 & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 2] = temp >> 40 & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 3] = temp >> 32 & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 4] = temp >> 24 & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 5] = temp >> 16 & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 6] = temp >> 8 & 0xFF;
		var[gVar_Count_Info[num].v_add * 2 + 7] = temp & 0xFF;
	}

	if (gVar_Count_Info[num].v_add >= VAR_ADDR_S)
		reg_operation(gVar_Count_Info[num].v_add);
	page_date_update(pic_id);

	if (finish == 1)
	{
		var[gVar_Count_Info[num].c_add * 2] = (gVar_Count_Info[num].V_stop >> 8) & 0xFF;
		var[gVar_Count_Info[num].c_add * 2 + 1] = gVar_Count_Info[num].V_stop  & 0xFF;

		if (gVar_Count_Info[num].feedback == 1)
		{
			if (gVar_Count_Info[num].v_type == 0x00 ||
				gVar_Count_Info[num].v_type == 0x80 ||
				gVar_Count_Info[num].v_type == 0x01 ||
				gVar_Count_Info[num].v_type == 0x81)
			{
				rebuf[3] = 0x41;
				rebuf[4] = gVar_Count_Info[num].v_add >> 8;;
				rebuf[5] = gVar_Count_Info[num].v_add & 0xFF;;
				rebuf[6] = var[gVar_Count_Info[num].v_add * 2];
				rebuf[7] = var[gVar_Count_Info[num].v_add * 2 + 1];
				Var_AddrToReg(&rebuf[4]);
				LT_SendData_CRC_Frame(rebuf, 5);
			}
			else if (gVar_Count_Info[num].v_type == 0x02 || gVar_Count_Info[num].v_type == 0x82)
			{
				rebuf[3] = 0x41;
				rebuf[4] = gVar_Count_Info[num].v_add >> 8;;
				rebuf[5] = gVar_Count_Info[num].v_add & 0xFF;;
				rebuf[6] = var[gVar_Count_Info[num].v_add * 2];
				rebuf[7] = var[gVar_Count_Info[num].v_add * 2 + 1];
				rebuf[8] = var[gVar_Count_Info[num].v_add * 2 + 2];
				rebuf[9] = var[gVar_Count_Info[num].v_add * 2 + 3];
				Var_AddrToReg(&rebuf[4]);
				LT_SendData_CRC_Frame(rebuf, 7);
			}
			else if (gVar_Count_Info[num].v_type == 0x03 || gVar_Count_Info[num].v_type == 0x83)
			{
				rebuf[3] = 0x41;
				rebuf[4] = gVar_Count_Info[num].v_add >> 8;;
				rebuf[5] = gVar_Count_Info[num].v_add & 0xFF;;
				rebuf[6] = var[gVar_Count_Info[num].v_add * 2];
				rebuf[7] = var[gVar_Count_Info[num].v_add * 2 + 1];
				rebuf[8] = var[gVar_Count_Info[num].v_add * 2 + 2];
				rebuf[9] = var[gVar_Count_Info[num].v_add * 2 + 3];
				rebuf[10] = var[gVar_Count_Info[num].v_add * 2 + 4];
				rebuf[11] = var[gVar_Count_Info[num].v_add * 2 + 5];
				rebuf[12] = var[gVar_Count_Info[num].v_add * 2 + 6];
				rebuf[13] = var[gVar_Count_Info[num].v_add * 2 + 7];
				Var_AddrToReg(&rebuf[4]);
				LT_SendData_CRC_Frame(rebuf, 11);
			}
		}

		for (uint8_t i = 0; i < 8; i++)
		{
			if (gVar_Count_Info[num].var_addr[i] != 0xFFFF && gVar_Count_Info[num].var_addr[i] < VAR_ADDR_E)
			{
				var[gVar_Count_Info[num].var_addr[i] * 2] = (gVar_Count_Info[num].var[i] >> 8) & 0xFF;
				var[gVar_Count_Info[num].var_addr[i] * 2 + 1] = gVar_Count_Info[num].var[i] & 0xFF;

				if (gVar_Count_Info[num].var_addr[i] > VAR_ADDR_S)
					reg_operation(gVar_Count_Info[num].var_addr[i]);
				else if (gVar_Count_Info[num].var_addr[i] == VAR_ADDR_S)
					page_flag = 1;
			}
		}

		if (page_flag == 1) reg_operation(VAR_ADDR_S);
		page_date_update(pic_id);
	}
}
